package com.yuju.pay.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.security.KeyStore;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.springframework.stereotype.Service;

import com.wxpay.common.WxConstant;
import com.wxpay.utils.GetWxOrderno;
import com.wxpay.utils.RequestHandler;
import com.wxpay.utils.TenpayUtil;
import com.yuju.cache.RedisCache;
import com.yuju.common.Result;
import com.yuju.constant.CacheKey;
import com.yuju.constant.Constant;
import com.yuju.enums.ReturnStatusEnum;
import com.yuju.enums.StatusEnum;
import com.yuju.enums.WxPayForScanReturnCodeEnum;
import com.yuju.exception.BusinessException;
import com.yuju.pay.service.WeChatPayService;
import com.yuju.util.ConfigUtil;

@Service("wxPayService")
public class WeChatPayServiceImpl implements WeChatPayService {
	private RedisCache<String, String> cache = RedisCache.getInstance();
	
	/**
	 * 元转换成分
	 * 
	 * @param money
	 * @return
	 */
	public String getMoney(String amount) {
		if (amount == null) {
			return "";
		}
		// 金额转化为分为单位
		String currency = amount.replaceAll("\\$|\\￥|\\,", ""); // 处理包含, ￥
																// 或者$的金额
		int index = currency.indexOf(".");
		int length = currency.length();
		Long amLong = 0l;
		if (index == -1) {
			amLong = Long.valueOf(currency + "00");
		} else if (length - index >= 3) {
			amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
		} else if (length - index == 2) {
			amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
		} else {
			amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
		}
		return amLong.toString();
	}
	
	/**
	 * 获取随机字符串
	 * 
	 * @return
	 */
	public String getNonceStr() {
		// 随机数
		String currTime = TenpayUtil.getCurrTime();
		// 8位日期
		String strTime = currTime.substring(8, currTime.length());
		// 四位随机数
		String strRandom = TenpayUtil.buildRandom(4) + "";
		// 10位序列号,可以自行调整。
		return strTime + strRandom;
	}
	/**
	 * 
	 * 功能: <br/>
	 * 
	 * @Date ：2018年1月17日 下午4:59:55<br/>
	 * 重写：sunyl <br/>
	 * @param out_trade_no 订单号
	 * @param auth_code 授权码
	 * @param spbill_create_ip 终端ip
	 * @return <br/>
	 * @throws Exception 
	 * @see com.yuju.WeChatPayService.service.WxPayService#wxPayForScanCode(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public Result microPay(BigDecimal money,String out_trade_no, String auth_code, String spbill_create_ip,String flag) throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String nonce_str = getNonceStr();
        data.put("appid", appid);
        data.put("auth_code", auth_code);
        data.put("body", "门店扫码");
        data.put("mch_id",mch_id);
        data.put("nonce_str", nonce_str);
        data.put("out_trade_no", out_trade_no);
		String totalFee = getMoney(money.toString());
		// 这里写的金额为1 分到时修改
		data.put("spbill_create_ip", spbill_create_ip);
        data.put("total_fee", totalFee);// totalFee
        
        RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), ConfigUtil.get(WxConstant.APP_SECRET), ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		 String url = "https://api.mch.weixin.qq.com/pay/micropay";
		 String  xml = "<xml>"+
			   "<appid>"+appid+"</appid>"+
			   "<auth_code>"+auth_code+"</auth_code>"+
			   "<body>门店扫码</body>"+
			   "<mch_id>"+mch_id+"</mch_id>"+
			   "<nonce_str>"+nonce_str+"</nonce_str>"+
			   "<out_trade_no>"+out_trade_no+"</out_trade_no>"+
			   "<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"+
			   "<total_fee>"+totalFee+"</total_fee>"+
			   "<sign>"+sign+"</sign>"+
			"</xml>";
		 return  handelPayResult(GetWxOrderno.getHttpMap(url, xml),out_trade_no,flag);
	}
	/**
	 * 服务商
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @Date 2018年2月6日 上午9:53:20 <br/>
	 */
	@Override
	public Result microPayForService(String hotelId,String groupId,BigDecimal money,String out_trade_no, String auth_code, String spbill_create_ip,String flag) throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
		/*String appid = ConfigUtil.get(WxConstant.APP_ID);*/
		String appid = cache.get(groupId+Constant.APP_ID+CacheKey.KEY_GRP_PARAM);
		String mch_id = cache.get(groupId+Constant.MCH_ID+CacheKey.KEY_GRP_PARAM);
		String sub_mch_id = cache.get(hotelId+Constant.HOTEL_MCH_ID+CacheKey.KEY_HOT_PARAM);
		//String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		//String sub_mch_id = "1498287672";
		String nonce_str = getNonceStr();
		// 这里写的金额为1 分到时修改
		String totalFee = getMoney(money.toString());
		data.put("appid", appid);
		data.put("auth_code", auth_code);
		data.put("body", "门店扫码");
		data.put("mch_id",mch_id);//1497953662
		data.put("nonce_str", nonce_str);
		data.put("out_trade_no", out_trade_no);
		data.put("spbill_create_ip", spbill_create_ip);
		data.put("sub_mch_id", sub_mch_id);
		data.put("total_fee", totalFee);// totalFee
		System.out.println(data.toString());
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(cache.get(groupId+Constant.APP_ID+CacheKey.KEY_GRP_PARAM),
				cache.get(groupId+Constant.APP_SECRET+CacheKey.KEY_GRP_PARAM),
				cache.get(groupId+Constant.MCH_KEY+CacheKey.KEY_GRP_PARAM));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/pay/micropay";
		String xml = "<xml>"
					   +"<appid>"+appid+"</appid>"
					   +"<auth_code>"+auth_code+"</auth_code>"
					   +"<body>门店扫码</body>"
					   +"<mch_id>"+mch_id+"</mch_id>"
					+"<sub_mch_id>"+sub_mch_id+"</sub_mch_id>"
					   +"<nonce_str>"+nonce_str+"</nonce_str>"
					   +"<out_trade_no>"+out_trade_no+"</out_trade_no>"
					   +"<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"
					   +"<total_fee>"+totalFee+"</total_fee>"
					   +"<sign>"+sign+"</sign>"
					+"</xml>";
		System.out.println("url："+url+"请求的xml:"+xml);
		return  handelPayResultForService(hotelId,groupId,GetWxOrderno.getHttpMap(url, xml),out_trade_no,flag);
	}
	/**
	 * 处理支付返回结果
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @throws Exception 
	 * @Date 2018年1月18日 下午6:04:47 <br/>
	 */
	private Result handelPayResult(Map resultMap,String orderNo,String flag) throws Exception{
		Result result  = new Result();
		String retrun_code = resultMap.get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		String result_code = resultMap.get("result_code").toString();
		Object err_code = resultMap.get("err_code");
		long times = 0;
		Object err_code_des = resultMap.get("err_code_des");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
				result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
			}else{
				if(err_code.toString().equals("USERPAYING")){
						result = handelQueryResult(orderNo, flag,times);
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
					result.setData(err_code_des);
				}
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
	}
	/**
	 * 处理支付返回结果
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @throws Exception 
	 * @Date 2018年1月18日 下午6:04:47 <br/>
	 */
	private Result handelPayResultForService(String hotelId,String groupId,Map resultMap,String orderNo,String flag) throws Exception{
		Result result  = new Result();
		Object retrun_code = resultMap.get("return_code");
		Object return_msg = resultMap.get("return_msg");
		Object result_code = resultMap.get("result_code");
		Object err_code = resultMap.get("err_code");
		long times = 0;
		Object err_code_des = resultMap.get("err_code_des");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
				result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
			}else{
				if(err_code.toString().equals("USERPAYING")){
					result = handelQueryResultForService(hotelId,groupId,orderNo, flag,times);
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
					result.setData(err_code_des);
				}
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
	}
	/**
	 * 查询并处理支付结果
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @Date 2018年1月18日 下午6:09:53 <br/>
	 */
	private Result handelQueryResult(String orderNo,String flag,long times) throws Exception{
		Thread.sleep(5000);//停顿5秒，继续查询
		times = times + 5000;
		if(times >= 30000){
			throw new BusinessException(WxPayForScanReturnCodeEnum.PAY_OUTTIME_FAILURE.getCode()
					,WxPayForScanReturnCodeEnum.PAY_OUTTIME_FAILURE.getDesc());
		}
		Result result  = new Result();
		Map resultMap = orderQuery(orderNo);//查询操作
		String retrun_code = resultMap.get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		String result_code = resultMap.get("result_code").toString();
		Object err_code_des = resultMap.get("err_code_des");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				String trade_state = resultMap.get("trade_state").toString();
				Object trade_state_desc = resultMap.get("trade_state_desc");
				if(trade_state.toString().equals("SUCCESS")){
					result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
					result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
					result.setData(resultMap);
				}else if(trade_state.toString().equals("USERPAYING")){
				
					result = handelQueryResult(orderNo,flag,times);
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
					result.setData(trade_state_desc);
				}
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
				result.setData(err_code_des);
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
	}
	/**
	 * 处理支付结果服务商
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @Date 2018年1月18日 下午6:09:53 <br/>
	 */
	private Result handelQueryResultForService(String hotelId,String groupId,String orderNo,String flag,long times) throws Exception{
		Result result  = new Result();
		Thread.sleep(5000);
		times = times + 5000;
		/*超时取消订单*/
		if(times >= 30000){
			Result re = reverseForService(orderNo, groupId, hotelId);
			if(re.getStatus() == ReturnStatusEnum.SUCCESS.getCode()){
				result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_SUCCESS.getDesc());
			}else{
				result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getDesc());
				result.setData(re.getData());
				
			}
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
		}
		/*if(times >= 30000){
			throw new BusinessException(WxPayForScanReturnCodeEnum.PAY_OUTTIME_FAILURE.getCode()
					,WxPayForScanReturnCodeEnum.PAY_OUTTIME_FAILURE.getDesc());
		}*/
		
		Map resultMap = orderQueryForService(hotelId,groupId,orderNo);
		Object retrun_code = resultMap.get("return_code");
		Object return_msg = resultMap.get("return_msg");
		if(retrun_code.equals("SUCCESS")){
			String result_code = resultMap.get("result_code").toString();
			Object err_code_des = resultMap.get("err_code_des");
			if(result_code.equals("SUCCESS")){
				String trade_state = resultMap.get("trade_state").toString();
				Object trade_state_desc = resultMap.get("trade_state_desc");
				if(trade_state.toString().equals("SUCCESS")){
					result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
					result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
					result.setData(resultMap);
				}else if(trade_state.toString().equals("USERPAYING")){
					result = handelQueryResultForService(hotelId,groupId,orderNo,flag,times);
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
					result.setData(trade_state_desc);
				}
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
				result.setData(err_code_des);
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
	}
	
	/**
	 * 微信刷卡扫码支付查询
	 * 功能: <br/>
	 * 
	 * 重写：sunyl <br/>
	 * 
	 * @Date ：2018年1月18日 上午10:46:54<br/>
	 * 
	 * @param out_trade_no
	 * @return
	 * @throws Exception <br/>
	 * @see com.yuju.WeChatPayService.service.WxPayService#orderQuery(java.lang.String)
	 */
	@Override
	public Map orderQuery(String out_trade_no) throws Exception{
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String nonce_str = getNonceStr();
        data.put("appid",appid );
        data.put("mch_id",mch_id );
        data.put("nonce_str", nonce_str);
        data.put("out_trade_no", out_trade_no);
        
        RequestHandler reqHandler = new RequestHandler(null, null);
        reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), 
        		ConfigUtil.get(WxConstant.APP_SECRET), 
        		ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		 String url = "https://api.mch.weixin.qq.com/pay/orderquery";
		 String xml  = "<xml>"
		   +"<appid>"+appid+"</appid>"
		   +"<mch_id>"+mch_id+"</mch_id>"
		   +"<nonce_str>"+nonce_str+"</nonce_str>"
		   +"<out_trade_no>"+out_trade_no+"</out_trade_no>"
		   +"<sign>"+sign+"</sign>"
		+"</xml>";
		return GetWxOrderno.getHttpMap(url, xml);
	}
	/**
	 * 服务商查询
	 * 功能: <br/>
	 * 
	 * 重写：xuehj <br/>
	 * 
	 * @Date ：2018年2月6日 上午11:41:37<br/>
	 * 
	 * @param out_trade_no
	 * @return
	 * @throws Exception <br/>
	 * @see com.yuju.WeChatPayService.service.WxPayService#orderQueryForService(java.lang.String)
	 */
	@Override
	public Map orderQueryForService(String hotelId,String groupId,String out_trade_no) throws Exception{
		SortedMap<String, String> data = new TreeMap<String, String>();
		/*String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String mch_id = "1497953662";
		String sub_mch_id = "1498287672";*/
		String appid = cache.get(groupId+Constant.APP_ID+CacheKey.KEY_GRP_PARAM);
		String mch_id = cache.get(groupId+Constant.MCH_ID+CacheKey.KEY_GRP_PARAM);
		String sub_mch_id = cache.get(hotelId+Constant.HOTEL_MCH_ID+CacheKey.KEY_HOT_PARAM);
		String nonce_str = getNonceStr();
		data.put("appid",appid );
		data.put("mch_id",mch_id );
		data.put("nonce_str", nonce_str);
		data.put("out_trade_no", out_trade_no);
		data.put("sub_mch_id", sub_mch_id);
		
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(cache.get(groupId+Constant.APP_ID+CacheKey.KEY_GRP_PARAM),
				cache.get(groupId+Constant.APP_SECRET+CacheKey.KEY_GRP_PARAM),
				cache.get(groupId+Constant.MCH_KEY+CacheKey.KEY_GRP_PARAM));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/pay/orderquery";
		String xml  = "<xml>"
				+"<appid>"+appid+"</appid>"
				+"<mch_id>"+mch_id+"</mch_id>"
				+"<nonce_str>"+nonce_str+"</nonce_str>"
				+"<out_trade_no>"+out_trade_no+"</out_trade_no>"
				+"<sub_mch_id>"+sub_mch_id+"</sub_mch_id>"
				+"<sign>"+sign+"</sign>"
				+"</xml>";
		return GetWxOrderno.getHttpMap(url, xml);
	}
	/**
	 * 撤销
	 * 功能: <br/>
	 * 
	 * 重写：xuehj <br/>
	 * 
	 * @Date ：2018年2月6日 上午11:41:49<br/>
	 * 
	 * @param out_trade_no
	 * @return
	 * @throws Exception <br/>
	 * @see com.yuju.WeChatPayService.service.WxPayService#reverse(java.lang.String)
	 */
	@Override
	public Map reverse(String out_trade_no) throws Exception{
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String nonce_str = getNonceStr();
		data.put("appid",appid );
		data.put("mch_id",mch_id );
		data.put("nonce_str", nonce_str);
		data.put("out_trade_no", out_trade_no);
		
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), 
				ConfigUtil.get(WxConstant.APP_SECRET), 
				ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
		String xml  = "<xml>"
				+"<appid>"+appid+"</appid>"
				+"<mch_id>"+mch_id+"</mch_id>"
				+"<nonce_str>"+nonce_str+"</nonce_str>"
				+"<out_trade_no>"+out_trade_no+"</out_trade_no>"
				+"<sign>"+sign+"</sign>"
				+"</xml>";
		return GetWxOrderno.getHttpMap(url, xml);
	}
	/**
	 * 撤銷訂單
	 * 功能: <br/>
	 * 
	 * 重写：xuehj <br/>
	 * 
	 * @Date ：2018年2月5日 上午10:33:19<br/>
	 * 
	 * @param money
	 * @param out_trade_no
	 * @param auth_code
	 * @param spbill_create_ip
	 * @param flag  本來是爲了區分預訂單和訂單額區別，沒用了
	 * @return
	 * @throws Exception <br/>
	 * @see com.yuju.WeChatPayService.service.WxPayService#reverse(java.math.BigDecimal, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public Result reverse(BigDecimal money, String out_trade_no, String auth_code, String spbill_create_ip, String flag)
			throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String nonce_str = getNonceStr();
        data.put("appid", appid);
        data.put("auth_code", auth_code);
        data.put("body", "门店扫码");
        data.put("mch_id",mch_id);
        data.put("nonce_str", nonce_str);
        data.put("out_trade_no", out_trade_no);
		String totalFee = getMoney(money.toString());
		// 这里写的金额为1 分到时修改
		data.put("spbill_create_ip", spbill_create_ip);
        data.put("total_fee", totalFee);// totalFee
        
        RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), ConfigUtil.get(WxConstant.APP_SECRET), ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		 String url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
		 String xml = "<xml>"
					   +"<appid>"+appid+"</appid>"
					   +"<mch_id>"+mch_id+"</mch_id>"
					   +"<nonce_str>"+nonce_str+"</nonce_str>"
					   +"<out_trade_no>"+out_trade_no+"</out_trade_no>"
					   +"<sign>"+sign+"</sign>"
					+"</xml>";
		 
		 Result result  = new Result();
		 Map resultMap  = GetWxOrderno.getHttpMap(url, xml);
			String retrun_code = resultMap .get("return_code").toString();
			Object return_msg = resultMap.get("return_msg");
			String result_code = resultMap.get("result_code").toString();
			Object err_code_des = resultMap.get("err_code_des");
			String recall = resultMap.get("recall").toString();
			if(retrun_code.equals("SUCCESS")){
				if(result_code.equals("SUCCESS")){
					result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
					result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_SUCCESS.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_SUCCESS.getDesc());
				}else{
					if(recall.equals("Y")){
						return this.reverse(money, out_trade_no, auth_code, spbill_create_ip, flag);
					}else{
						result.setStatus(ReturnStatusEnum.FAILURE.getCode());
						result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
						result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getCode());
						result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getDesc());
						result.setData(err_code_des);
					}
				}
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getDesc());
				result.setData(return_msg);
			}
			return result;
		 
	}
	@Override
	public Result reverseForService(String out_trade_no, String groupId,String hotelId)
			throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = cache.get(groupId+Constant.APP_ID+CacheKey.KEY_GRP_PARAM);
		String mch_id = cache.get(groupId+Constant.MCH_ID+CacheKey.KEY_GRP_PARAM);
		String sub_mch_id = cache.get(hotelId+Constant.HOTEL_MCH_ID+CacheKey.KEY_HOT_PARAM);
		String nonce_str = getNonceStr();
		data.put("appid",appid);
		data.put("mch_id",mch_id);
		data.put("nonce_str",nonce_str);
		data.put("out_trade_no",out_trade_no);
		data.put("sub_mch_id",sub_mch_id);
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(cache.get(groupId+Constant.APP_ID+CacheKey.KEY_GRP_PARAM),
				cache.get(groupId+Constant.APP_SECRET+CacheKey.KEY_GRP_PARAM),
				cache.get(groupId+Constant.MCH_KEY+CacheKey.KEY_GRP_PARAM));
		
		String sign = reqHandler.createSign(data);
		//data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
		String xml = "<xml>"
					   +"<appid>"+appid+"</appid>"
					   +"<mch_id>"+mch_id+"</mch_id>"
					   +"<nonce_str>"+nonce_str+"</nonce_str>"
					   + "<sub_mch_id>"+sub_mch_id+"</sub_mch_id>"
					   +"<out_trade_no>"+out_trade_no+"</out_trade_no>"
					   +"<sign>"+sign+"</sign>"
					+"</xml>";
		FileInputStream instream = new FileInputStream(new File("F:/cert/apiclient_cert.p12"));
		Result result  = new Result();
		Map resultMap  = GetWxOrderno.getRefund(url, instream, xml, mch_id);
		String retrun_code = resultMap .get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		Object result_code = resultMap.get("result_code");
		Object err_code_des = resultMap.get("err_code_des");
		Object recall = resultMap.get("recall");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
				result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_SUCCESS.getDesc());
			}else{
				if(recall.equals("Y")){
					return this.reverseForService(out_trade_no,groupId,hotelId);
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getDesc());
					result.setData(err_code_des);
				}
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
	}
	/**
	 * 撤銷訂單
	 * 功能: <br/>
	 * 
	 * 重写：xuehj <br/>
	 * 
	 * @Date ：2018年2月5日 上午10:33:19<br/>
	 * 
	 * @param money
	 * @param out_trade_no
	 * @param auth_code
	 * @param spbill_create_ip
	 * @param flag  本來是爲了區分預訂單和訂單額區別，沒用了
	 * @return
	 * @throws Exception <br/>
	 * @see com.yuju.WeChatPayService.service.WxPayService#reverse(java.math.BigDecimal, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public Result refund(BigDecimal refund_fee,BigDecimal total_fee, String out_trade_no, String transaction_id, String flag)
			throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String nonce_str = getNonceStr();
		data.put("appid", appid);
		data.put("mch_id",mch_id);
		data.put("nonce_str", nonce_str);
		data.put("out_trade_no", out_trade_no);
		data.put("out_refund_no", out_trade_no);
		String totalFee = getMoney(total_fee.toString());
		String refundFee = getMoney(refund_fee.toString());
		// 这里写的金额为1 分到时修改
		data.put("refund_fee", refundFee);// totalFee
		data.put("total_fee", totalFee);// totalFee
		data.put("transaction_id", transaction_id);
		
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), ConfigUtil.get(WxConstant.APP_SECRET), ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
		String xml ="<xml>"
					   +"<appid>"+appid+"</appid>"
					   +"<mch_id>"+mch_id+"</mch_id>"
					   +"<nonce_str>"+nonce_str+"</nonce_str>" 
					   +"<out_refund_no>"+out_trade_no+"</out_refund_no>"
					   +"<out_trade_no>"+out_trade_no+"</out_trade_no>"
					   +"<refund_fee>"+refundFee+"</refund_fee>"
					   +"<total_fee>"+totalFee+"</total_fee>"
					   +"<transaction_id>"+transaction_id+"</transaction_id>"
					   +"<sign>"+sign+"</sign>"
					+"</xml>";
		System.out.println("请求的url:"+url+"xml:"+xml);
		KeyStore keyStore  = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File("F:/cert/apiclient_cert.p12"));
		Result result  = new Result();
		Map resultMap  = GetWxOrderno.getRefund(url, instream, xml, mch_id);
		String retrun_code = resultMap .get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		Object result_code = resultMap.get("result_code");
		Object err_code_des = resultMap.get("err_code_des");
		Object recall = resultMap.get("recall");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
				result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_SUCCESS.getDesc());
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getDesc());
				result.setData(err_code_des);
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
		
	}
	@Override
	public Result refundForService(String hotelId,String groupId,BigDecimal refund_fee,BigDecimal total_fee, String out_trade_no,String out_refund_no, String transaction_id, String flag)
			throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
		/*String appid = ConfigUtil.get(WxConstant.APP_ID);*/
		/*		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);*/
/*		String appid = cache.get(groupId+Constant.APP_ID+CacheKey.KEY_GRP_PARAM);
		String mch_id = cache.get(groupId+Constant.MCH_ID+CacheKey.KEY_GRP_PARAM);
		String sub_mch_id = cache.get(hotelId+Constant.HOTEL_MCH_ID+CacheKey.KEY_HOT_PARAM);*/
		String appid = cache.get(groupId+Constant.APP_ID+CacheKey.KEY_GRP_PARAM);
		String mch_id = cache.get(groupId+Constant.MCH_ID+CacheKey.KEY_GRP_PARAM);
		String sub_mch_id = cache.get(hotelId+Constant.HOTEL_MCH_ID+CacheKey.KEY_HOT_PARAM);
		//String mch_id = "1497953662";
		//String sub_mch_id = "1498287672";
		String nonce_str = getNonceStr();
		data.put("appid", appid);
		data.put("mch_id",mch_id);
		data.put("nonce_str", nonce_str);
		data.put("out_trade_no", out_trade_no);
		data.put("out_refund_no", out_trade_no);
		String totalFee = getMoney(total_fee.toString());
		String refundFee = getMoney(refund_fee.toString());
		// 这里写的金额为1 分到时修改
		data.put("refund_fee", refundFee);// totalFee
		data.put("sub_mch_id", sub_mch_id);
		data.put("total_fee", totalFee);// totalFee
		data.put("transaction_id", transaction_id);
		
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(cache.get(groupId+Constant.APP_ID+CacheKey.KEY_GRP_PARAM),
				cache.get(groupId+Constant.APP_SECRET+CacheKey.KEY_GRP_PARAM),
				cache.get(groupId+Constant.MCH_KEY+CacheKey.KEY_GRP_PARAM));
		String sign = reqHandler.createSign(data);
		data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
		String xml ="<xml>"
				+"<appid>"+appid+"</appid>"
				+"<mch_id>"+mch_id+"</mch_id>"
				+"<nonce_str>"+nonce_str+"</nonce_str>" 
				+"<sub_mch_id>"+sub_mch_id+"</sub_mch_id>"
				+"<out_refund_no>"+out_trade_no+"</out_refund_no>"
				+"<out_trade_no>"+out_trade_no+"</out_trade_no>"
				+"<refund_fee>"+refundFee+"</refund_fee>"
				+"<total_fee>"+totalFee+"</total_fee>"
				+"<transaction_id>"+transaction_id+"</transaction_id>"
				+"<sign>"+sign+"</sign>"
				+"</xml>";
		System.out.println("请求的url:"+url+"xml:"+xml);
		KeyStore keyStore  = KeyStore.getInstance("PKCS12");
		FileInputStream instream = new FileInputStream(new File("F:/cert/apiclient_cert.p12"));
		Result result  = new Result();
		Map resultMap  = GetWxOrderno.getRefund(url, instream, xml, mch_id);
		String retrun_code = resultMap .get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		Object result_code = resultMap.get("result_code");
		Object err_code_des = resultMap.get("err_code_des");
		Object recall = resultMap.get("recall");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
				result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_SUCCESS.getDesc());
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getDesc());
				result.setData(err_code_des);
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
	}
}
